using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Configuration.Install;
using System.Data;
using System.Data.SqlClient;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Text;
using System.Windows.Forms;
using System.Threading;

using Microsoft.Vsts.Ranger.Migration.TfsToTfs.Service.Common;

namespace TfsMigrationWindowsServiceHost
{
    [RunInstaller(true)]
    public partial class ProjectInstaller : Installer
    {
        private const string connectionStringName = "TfsMigrationService.Properties.Settings.TPCopyLoggingConnectionString";
        private string assemblyLocation;
        private SqlConnectionStringBuilder connectionStringBuilder;
        private System.Configuration.Configuration config;
        private InstallContext installContext;

        public ProjectInstaller()
        {
            InitializeComponent();

            this.serviceInstaller.ServiceName = Constants.CMIGRATIONSERVICENAME;

            assemblyLocation = Assembly.GetExecutingAssembly().Location;

            

            this.installContext = new InstallContext(Path.Combine(Directory.GetParent(assemblyLocation).FullName, "InstallLog.txt"),null);

            
            //open app.config
            config = ConfigurationManager.OpenExeConfiguration(assemblyLocation);

            connectionStringBuilder = new SqlConnectionStringBuilder();

            // Verify if the config file exists
            if (File.Exists(assemblyLocation))
            {
                //Load default connectionString
                connectionStringBuilder.ConnectionString =
                    config.ConnectionStrings.ConnectionStrings[connectionStringName].ConnectionString;
            }

            this.installContext.LogMessage("Starting Install: " + DateTime.Now.ToString());
        }

        public override void Install(System.Collections.IDictionary stateSaver)
        {
            try
            {
                base.Install(stateSaver);
            }
            catch (Exception ex)
            {
                this.installContext.LogMessage("An Error Has Occurred.  Check The Install Log: " + ex.Message);
                throw;
            }


            DatabaseConnection dbConnection = new DatabaseConnection();
            dbConnection.ConnectionStringBuilder = connectionStringBuilder;

            DialogResult ret = dbConnection.ShowDialog();

            // If user cancelled abort installation
            if (ret != DialogResult.OK)
            {
                throw new Exception();
            }

            try
            {
                //Build new connection string
                connectionStringBuilder.DataSource = dbConnection.ServerName;
                connectionStringBuilder.InitialCatalog = dbConnection.DatabaseName;
                connectionStringBuilder.IntegratedSecurity = true;

                config.ConnectionStrings.ConnectionStrings[connectionStringName].ConnectionString =
                    connectionStringBuilder.ConnectionString;

                config.Save(ConfigurationSaveMode.Modified);

                //Save it for the next invocation
                stateSaver.Add("ConnectString", connectionStringBuilder.ConnectionString);

                if (dbConnection.CreateDatabase)
                    ExecuteInstallScript(dbConnection.ServerName );

                //try
                //{
                //    System.ServiceProcess.ServiceController controller = new System.ServiceProcess.ServiceController(this.serviceInstaller.ServiceName);
                //    controller.Start();
                //}
                //catch (Exception ex)
                //{
                //    MessageBox.Show("Service Could Not Be Started Manually.  Please start Tfs to Tfs Migration Service Windows service manually before running application.  Error Starting:" + ex.Message);
                //}
            }
            catch (Exception ex)
            {
                this.installContext.LogMessage("An Error Has Occurred.  Check The Install Log: " + ex.Message);
                throw;
            }

        }

        public override void Uninstall(System.Collections.IDictionary stateSaver)
        {
            try
            {
                base.Uninstall(stateSaver);
            }
            catch (Exception ex)
            {
                this.installContext.LogMessage("An Error Has Occurred.  Check The Install Log: " + ex.Message);
                throw;
            }

            DialogResult result = MessageBox.Show("Do you want to delete the database?", "Uninstall", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1);
                
            if (result == DialogResult.Yes)
            {
                try
                {
                    ExecuteUninstallScript();
                }
                catch (Exception ex)
                {
                    MessageBox.Show("An error has occurred removing the database.  Please check the installation log for details.  The uninstall will proceed, but the database will remain, so please delete it manually.");
                    this.installContext.LogMessage("An Error Has Occurred.  Check The Install Log: " + ex.Message);
                }
            }
        }

        private void ExecuteUninstallScript()
        {
            SqlConnection connection = new SqlConnection(connectionStringBuilder.ConnectionString);

            

            connection.Open();


            SqlCommand command = connection.CreateCommand();
            command.CommandText = string.Format("USE [master] \n DROP DATABASE [{0}]", connectionStringBuilder.InitialCatalog);
            command.CommandType = CommandType.Text;

            command.ExecuteNonQuery();
        }

        /// <summary>
        /// Executes the install script
        /// </summary>
        private void ExecuteInstallScript(string serverName)
        {
            int indexOf = Assembly.GetExecutingAssembly().Location.LastIndexOf("\\");
            string path = Assembly.GetExecutingAssembly().Location.Substring(0, indexOf);

            //Surround the filename in quotes in case there are spaces in the path
            string scriptLocation = "\"" + path + "\\Database.(local)_SQLEXPRESS.TfsToTfsMigrationTool.sql" + "\"";

            ProcessStartInfo startInfo = new ProcessStartInfo();
            startInfo.Arguments = "-i" + scriptLocation + " -S " + serverName;


            startInfo.CreateNoWindow = false;
            startInfo.FileName = "sqlcmd.exe";
            startInfo.RedirectStandardError = true;
            startInfo.RedirectStandardOutput = true;
            startInfo.StandardErrorEncoding = Encoding.UTF8;
            startInfo.StandardOutputEncoding = Encoding.UTF8;
            startInfo.UseShellExecute = false;
            startInfo.WindowStyle = ProcessWindowStyle.Normal;
            
            
            
            
            Process process = new Process();
            process.StartInfo = startInfo;
           

            process.Start();

            this.installContext.LogMessage(process.StandardOutput.ReadToEnd());
            this.installContext.LogMessage(process.StandardError.ReadToEnd());
            
            process.WaitForExit();

            installContext.LogMessage("Database Server: " + serverName);
            installContext.LogMessage("Database Installation Exit Code: " + process.ExitCode);

            if (process.ExitCode != 0)
                MessageBox.Show("Database installation completed with errors, please check installation log.", "Database Installation Error");

        }

        
    }
}
